package com.york.tinyrpc.protoss.fault.retry;

import com.github.rholder.retry.*;
import com.york.tinyrpc.protoss.model.TinyRpcResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 随机延迟时间间隔
 * 每次重试时间间隔随机
 */
public class RandomDelayRetryStrategy implements RetryStrategy {

    private static final Logger log = LoggerFactory.getLogger(RandomDelayRetryStrategy.class);

    // 最小延迟时间（单位：秒）
    private static final long MIN_DELAY = 1L;

    // 最大延迟时间（单位：秒）
    private static final long MAX_DELAY = 5L;

    // 最大重试次数
    private static final int MAX_ATTEMPTS = 3;

    @Override
    public TinyRpcResponse doRetry(Callable<TinyRpcResponse> target) throws ExecutionException, RetryException {
        Retryer<TinyRpcResponse> retryer = RetryerBuilder.<TinyRpcResponse>newBuilder()
                // 触发条件：遇到任何异常时重试
                .retryIfExceptionOfType(Exception.class)
                // 随机延迟策略：每次等待时间在 [1s, 5s] 范围内随机
                .withWaitStrategy(WaitStrategies.randomWait(MIN_DELAY, TimeUnit.SECONDS, MAX_DELAY, TimeUnit.SECONDS))
                // 停止策略：最多重试3次（含首次调用）
                .withStopStrategy(StopStrategies.stopAfterAttempt(MAX_ATTEMPTS))
                // 重试监听器（记录日志）
                .withRetryListener(new RetryListener() {
                    @Override
                    public <V> void onRetry(Attempt<V> attempt) {
                        long currentTime = attempt.getAttemptNumber();
                        if (currentTime > 1L) {
                            log.info("第 {} 次重试，等待时间随机区间：[{}s, {}s]",
                                    attempt.getAttemptNumber() - 1,
                                    MIN_DELAY,
                                    MAX_DELAY);
                        }
                    }
                })
                .build();
        return retryer.call(target);
    }
}
